﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Broadsides2d
{
    public abstract class Ship
    {
        public static List<Texture2D> image = new List<Texture2D>();
        public float x;
        public float y;
        private int[] cooldown = new int[2];
        
        protected int gold;
        protected int life;

        protected float rotation = 0f; // IN RADIANS
        private int cannonCooldown;
        protected float speed;
        protected float baseSpeed;

        private const float speedCapTop = 1.5f;
        private const float speedCapBot = .5f;
        
        protected const float rotationSpeed = .5f;
        protected const float scale = 1f;

        ShipType type;

        
        public Ship(float x, float y, ShipType type)
        {
            this.x = x;
            this.y =  y;
            this.type = type;
            cooldown[0] = cooldown [1] = cannonCooldown = 75;
            life = 20;
            speed = baseSpeed = 1.0f;
        }

        public virtual void Update()
        {
            moveShip();
            coolCannon(CannonSide.right);
            coolCannon(CannonSide.left);
        }

        public void moveShip()
        {
            clearTiles();
            if (life > 0)
            {
                float dx = ((x + (float)Math.Sin(rotation) * speed) + World.world.worldSizeInPixels) % World.world.worldSizeInPixels;
                float dy = ((y + (float)Math.Cos(rotation) * -1 * speed) + World.world.worldSizeInPixels) % World.world.worldSizeInPixels;


                if (this is NPC || !World.world.checkForLand(dx, dy))
                {
                    x = dx;
                    y = dy;
                }
                else // Crashes onto land
                {
                    life -= 25; ;
                    speed = -1;
                }

                for (int i = -2; i < (((rotation > MathHelper.PiOver4 && rotation < 3 * MathHelper.PiOver4) || (rotation > 5 * MathHelper.PiOver4 && rotation < 7 * MathHelper.PiOver4)) ? 4 : 3); i++)
                    for (int j = -2; j < (((rotation > MathHelper.PiOver4 && rotation < 3 * MathHelper.PiOver4) || (rotation > 5 * MathHelper.PiOver4 && rotation < 7 * MathHelper.PiOver4)) ? 3 : 4); j++)
                        World.world.tiles[((int)((x / 8) + i) + World.world.worldSize) % World.world.worldSize, ((int)((y / 8) + j) + World.world.worldSize) % World.world.worldSize].contents.Add(this);
            }

        }
        private void coolCannon(CannonSide side)
        {
            if(cooldown[(int)side] > 0)
                cooldown[(int)side]--;
        }

        public abstract void Draw(SpriteBatch batch);
        
        public void fireCannon(CannonSide side)
        {
            if (life > 0)
            {
                if (side == CannonSide.right)
                    if (cooldown[(int)CannonSide.right] == 0)
                    {
                        float direction = (float)(rotation + Math.PI / 2);
                        Game1.cannonballs.Add(new Cannonball((float)(x + (10 * Math.Cos(direction))), (float)(y + (10 * Math.Sin(direction))), direction, this));
                        Game1.cannonballs.Add(new Cannonball((float)(x - (10 * Math.Cos(direction))), (float)(y - (10 * Math.Sin(direction))), direction, this));
                        cooldown[0] = cannonCooldown;
                    }
                if (side == CannonSide.left)
                    if (cooldown[(int)CannonSide.left] == 0)
                    {
                        float direction = (float)(rotation - Math.PI / 2);
                        Game1.cannonballs.Add(new Cannonball((float)(x + (10 * Math.Cos(direction))), (float)(y + (10 * Math.Sin(direction))), direction, this));
                        Game1.cannonballs.Add(new Cannonball((float)(x - (10 * Math.Cos(direction))), (float)(y - (10 * Math.Sin(direction))), direction, this));
                        cooldown[1] = cannonCooldown;
                    }

            }
        }

        public void rotateShip(float rotation)
        {
            if(life > 0)
                this.rotation = (this.rotation + rotationSpeed * rotation + MathHelper.TwoPi) % MathHelper.TwoPi;
        }

        public void setSpeed( float speed)
        {
            this.speed = speed;
        }
        public float getBaseSpeed()
        {
            return this.baseSpeed;
        }
        public void setX(float x)
        {
            this.x = x;
        }
        public float getX()
        {
            return this.x;
        }
        public void setY(float y)
        {
            this.y = y;
        }
        public float getY()
        {
            return this.y;
        }
        public void setRotation(float rotation)
        {
            this.rotation = rotation;
        }
        public float getRotation()
        {
            return this.rotation;
        }
        public void setCurrentCooldown(CannonSide side, int cooldown)
        {
            this.cooldown[(int)side] = cooldown;
        }
        public int getCurrentCooldown(CannonSide side)
        {
            return this.cooldown[(int)side];
        }
        public void setBaseCooldown(int cooldown)
        {
            this.cannonCooldown = cooldown;
        }
        public int getBaseCooldown()
        {
            return this.cannonCooldown;
        }
        public void setGold(int gold)
        {
            this.gold = gold;
        }
        public int getGold()
        {
            return this.gold;
        }
        public void addGold(int gold)
        {
            this.gold += gold;
        }
        public void setLife(int life)
        {
            this.life = life;
        }
        public int getLife()
        {
            return this.life;
        }
        public void addLife(int life)
        {
            this.life += life;
        }
        public float getSpeed()
        {
            return speed;
        }
        public float getSpeedCapTop()
        {
            return speedCapTop;
        }
        public float getSpeedCapBot()
        {
            return speedCapBot;
        }
        public void clearTiles()
        {
            for (int i = -2; i < 4; i++)
                for (int j = -2; j < 4; j++)
                    if (World.world.tiles[((int)((x / 8) + i) + World.world.worldSize) % World.world.worldSize, ((int)((y / 8) + j) + World.world.worldSize) % World.world.worldSize].contents.Contains(this))
                        World.world.tiles[((int)((x / 8) + i) + World.world.worldSize) % World.world.worldSize, ((int)((y / 8) + j) + World.world.worldSize) % World.world.worldSize].contents.Remove(this);
        }

        public enum ShipType
        {
            player,
            neutral
        }

        public enum CannonSide
        {
            right,
            left
        }

    }
}
